package com.katze.boot.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.katze.boot.common.domain.ActiveUser;
import com.katze.boot.common.utils.AesEncryptUtils;
import com.katze.boot.common.utils.EncryptUtils;
import com.katze.boot.plugins.redis.service.CacheService;
import com.katze.boot.system.dao.UserMapper;
import com.katze.boot.system.dao.UserRoleMapper;
import com.katze.boot.system.domain.DeptUsers;
import com.katze.boot.system.domain.User;
import com.katze.boot.system.domain.UserRole;
import com.katze.boot.system.service.UserService;
import com.katze.boot.system.service.UserSetupService;
import com.katze.common.Pagination;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Date;
import java.util.List;

@Service("userService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UserSetupService userSetupService;
    @Autowired
    private CacheService cacheService;

    @Override
    public boolean exists(String username, String... password) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, username);
        if (password.length == 1) {
            wrapper.eq(User::getPassword, password[0]);
        }
        return this.exists(wrapper);
    }

    @Override
    public User findCacheByName(String username) {
        return this.cacheService.getUser(username, this::findDetailByName);
    }

    @Override
    public User findDetailByName(String username, String... password) {
        return this.baseMapper.findDetail(username, password.length == 1? password[0]:null);
    }

    @Override
    public List<ActiveUser> findUserByUsernames(Collection<String> username) {
        return this.baseMapper.findActiveUserByUsernames(username);
    }

    @Override
    public IPage<User> findUsers(User user, Pagination request) {
        return this.baseMapper.findUserDetail(request.toPage(OrderItem.asc("user_id")), user);
    }

    @Override
    @Transactional
    public void updateLoginTime(User user) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getLastLoginTime, user.getLastLoginTime())
                .set(User::getLastLoginIp, user.getLastLoginIp())
                .set(User::getLastLoginLocation, user.getLastLoginLocation())
                .eq(User::getUsername, user.getUsername());
        super.update(wrapper);
    }

    @Override
    @Transactional
    public void createUser(User user) {
        // 创建用户
        user.setCreateTime(new Date());
        user.setPassword(EncryptUtils.MD5Encrypt(user.getUsername(), User.DEFAULT_PASSWORD));
        user.setStatus(User.STATUS_NORMAL);
        this.save(user);

        // 保存用户角色
        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);
        // 创建用户默认的个性化配置
        userSetupService.initDefaultUserSetup(user.getUsername());
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        // 更新用户
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getFirstname, user.getFirstname())
                .set(User::getMobile, user.getMobile())
                .set(User::getEmail, user.getEmail())
                .set(User::getSex, user.getSex())
                .set(User::getStatus, user.getStatus())
                .set(User::getAddress, user.getAddress())
                .set(User::getBirthDate, user.getBirthDate())
                .set(User::getDeptId, user.getDeptId())
                .set(User::getDescription, user.getDescription())
                .set(User::getModifyTime, user.getModifyTime())
                .eq(User::getUserId, user.getUserId());
        super.update(wrapper);

        this.userRoleMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, user.getUserId()));

        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);

        // 重新将用户信息，用户角色信息，用户权限信息 加载到 redis中
        cacheService.clearUserCache(user.getUsername());
    }

    @Override
    @Transactional
    public void deleteUsers(String... usernames) {
        for (String username : usernames) {
            // 先删除相应的缓存
            this.cacheService.clearUserCache(username);
            // 删除用户, 用户个性化配置, 用户角色
            this.baseMapper.deleteUserByUsername(username);
        }
    }

    @Override
    @Transactional
    public void updateProfile(User user) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(StringUtils.isNotBlank(user.getFirstname()), User::getFirstname, user.getFirstname())
                .set(StringUtils.isNotBlank(user.getSex()), User::getSex, user.getSex())
                .set(StringUtils.isNotBlank(user.getMobile()), User::getMobile, user.getMobile())
                .set(StringUtils.isNotBlank(user.getEmail()), User::getEmail, user.getEmail())
                .set(StringUtils.isNotBlank(user.getAvatar()), User::getAvatar, user.getAvatar())
                .set(StringUtils.isNotBlank(user.getStatus()), User::getStatus, user.getStatus());
        if (user.getBirthDate() != null) {
            wrapper.set(User::getBirthDate, user.getBirthDate().trim());
        }
        if (user.getDescription() != null) {
            wrapper.set(User::getDescription, user.getDescription().trim());
        }
        if (user.getAddress() != null) {
            wrapper.set(User::getAddress, user.getAddress().trim());
        }
        wrapper.eq(User::getUserId, user.getUserId());
        super.update(wrapper);
        // 重新缓存用户信息
        cacheService.clearUserCache(user.getUsername());
    }

    @Override
    @Transactional
    public void updateAvatar(String username, String avatar) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getAvatar, avatar)
                .eq(User::getUsername, username);
        super.update(wrapper);
        // 重新缓存用户信息
        cacheService.clearUserCache(username);
    }

    @Override
    @Transactional
    public void updatePassword(String username, String password) {
        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate(User.class)
                .set(User::getPassword, EncryptUtils.MD5Encrypt(username, password))
                .eq(User::getUsername, username);
        super.update(wrapper);
        // 重新缓存用户信息
        cacheService.clearUserCache(username);
    }

    @Override
    @Transactional
    public void regist(String username, String password) {
        User user = new User();
        user.setPassword(EncryptUtils.MD5Encrypt(username, AesEncryptUtils.desEncrypt(password)));
        user.setUsername(username);
        user.setCreateTime(new Date());
        user.setStatus(User.STATUS_LOCK);
        user.setSex(User.SEX_UNKNOW);
        user.setDescription("注册用户");
        super.save(user);

        UserRole ur = new UserRole();
        ur.setUserId(user.getUserId());
        ur.setRoleId(2L); // 注册用户角色 ID
        this.userRoleMapper.insert(ur);

        // 创建用户默认的个性化配置
        this.userSetupService.initDefaultUserSetup(username);
    }

    @Override
    @Transactional
    public void resetPassword(String[] usernames) {
        for (String username : usernames) {
            User user = new User();
            user.setPassword(EncryptUtils.MD5Encrypt(username, User.DEFAULT_PASSWORD));
            this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getUsername, username));
            // 重新缓存用户信息
            cacheService.clearUserCache(username);
        }

    }

    private void setUserRoles(User user, String... roles) {
        for (String role : roles) {
            UserRole ur = new UserRole();
            ur.setUserId(user.getUserId());
            ur.setRoleId(Long.valueOf(role));
            this.userRoleMapper.insert(ur);
        }
    }

    @Override
    public String findSubordinates(Long deptId) {
        return this.baseMapper.findSubordinates(deptId);
    }

    @Override
    public List<DeptUsers> findSubordinatesMap() {
        return baseMapper.findSubordinatesMap();
    }
}